use crate::context::{get_file_or_create, read_to_string};
use crate::AppResult;
use const_format::concatcp;
use serde::{Deserialize, Serialize};
use serde_json::{from_str, json};
use tokio::io::AsyncWriteExt;
use tokio::sync::OnceCell;
use tracing::info;
/** JetBrains插件市场基础URL */
const PLUGIN_BASIC_URL: &str = "https://plugins.jetbrains.com";

/** 插件列表API地址，获取所有插件基本信息 */
const PLUGIN_LIST_URL: &str = concatcp!(PLUGIN_BASIC_URL, "/api/searchPlugins");

/** 插件详情API地址模板，用于获取单个插件的详细信息 */
const PLUGIN_INFO_URL: &str = concatcp!(PLUGIN_BASIC_URL, "/api/plugins/");

/** 插件信息缓存文件路径 */
const PLUGIN_JSON_FILE_NAME: &str = "external/data/plugin.json";
static PLUGIN_LIST: OnceCell<Vec<PluginCache>> = OnceCell::const_new();
pub async fn get_plugin_list() -> &'static Vec<PluginCache> {
    PLUGIN_LIST
        .get_or_init(|| async {
            info!("开始初始化插件上下文...");
            let mut file = get_file_or_create(PLUGIN_JSON_FILE_NAME).await.unwrap();
            let string = read_to_string(&mut file).await.unwrap();
            let result = from_str::<Vec<PluginCache>>(&string);
            if let Ok(value) = result {
                value
            } else {
                let plugin_list = refresh_plugin_list().await.unwrap();
                file.write_all(json!(plugin_list).to_string().as_bytes())
                    .await
                    .unwrap();
                file.flush().await.unwrap();
                info!("插件列表刷新完成！");
                plugin_list
            }
        }).await
        }
    async fn refresh_plugin_list() -> AppResult<Vec<PluginCache>> {
    info!("开始刷新插件列表...");
    let client = reqwest::Client::new();
    let mut plugins = vec![];
        let mut offset = 0;
        loop{
            let plugin_list_obj = client
                .get(PLUGIN_LIST_URL)
                .query(&[("max", "20"), ("offset", offset.to_string().as_str()), ("pricingModels", "FREEMIUM"), ("pricingModels", "PAID")])
                .send()
                .await?
                .json::<PluginList>()
                .await?;
            //获取插件详情信息
            for plugin in plugin_list_obj.plugins {
                let plugin_info = client
                    .get(format!("{}{}", PLUGIN_INFO_URL, plugin.id))
                    .send()
                    .await?
                    .json::<PluginInfo>()
                    .await?;
               let plugin_cache = PluginCache {
                    id: plugin.id,
                    name: plugin.name,
                    product_code: plugin_info.purchase_info.product_code,
                    icon: if plugin.icon.is_some() {
                        let string = plugin.icon.unwrap();
                        PLUGIN_BASIC_URL.to_owned() + string.as_str()
                    } else {
                        PLUGIN_BASIC_URL.to_owned()
                    },
                    pricing_model: plugin.pricing_model,
                };
                plugins.push(plugin_cache);
            }
            info!("获取插件中...数量：{}",plugins.len());
            if offset>(plugin_list_obj.total-20) {
                break;
            }
            offset += 20;
        }
    Ok(plugins)
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PluginCache {
    /** 插件ID */
    pub id: u64,
    /** 插件名称 */
    pub name: String,
    /** 插件描述 */
    #[serde(rename = "productCode")]
    pub product_code: String,
    /** 插件图标 */
    pub icon: String,
    /** 插件作者 */
    #[serde(rename = "pricingModel")]
    pub pricing_model: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PluginInfo {
    /** 插件ID */
    pub id: u64,
    #[serde(rename = "purchaseInfo")]
    pub purchase_info: PurchaseInfo,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PurchaseInfo {
    product_code: String,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PluginList {
    total: u32,
    plugins: Vec<Plugin>,
}
// 转换后的Plugin结构体
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Plugin {
    id: u64,      // Java的Long对应Rust的i64，使用Option表示可能为null
    name: String, // Java的String对应Rust的String，使用Option表示可能为null
    preview: Option<String>,
    downloads: Option<i32>,
    pricing_model: String, // Rust中通常使用蛇形命名法
    organization: Option<String>,
    icon: Option<String>,
    preview_image: Option<String>,
    rating: Option<f64>,             // Java的Double对应Rust的f64
    vendor_info: Option<VendorInfo>, // 嵌套结构体，使用Option表示可能为null
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VendorInfo {
    name: String,
    #[serde(rename = "isVerified")]
    is_verified: bool,
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::SeekFrom;
    use tokio::io::AsyncSeekExt;
    use tracing_subscriber::fmt;
    use tracing_subscriber::layer::SubscriberExt;
    use tracing_subscriber::util::SubscriberInitExt;
    #[tokio::test]
    async fn test_get_plugin_list() {
        // 只有注册 subscriber 后， 才能在控制台上看到日志输出
        tracing_subscriber::registry()
            .with(
                fmt::layer()
                    .with_line_number(true)
                    .with_thread_names(true)
                    .compact(),
            )
            .init();
        // let plugin_list = get_plugin_list().await;
        // println!("{:?}", plugin_list);
        let mut file = get_file_or_create(PLUGIN_JSON_FILE_NAME).await.unwrap();
        let string = read_to_string(&mut file).await.unwrap();
        let result = from_str::<Vec<PluginCache>>(&string);
        match result {
            Ok(mut vec) => {
                for x in &mut vec {
                    x.icon = PLUGIN_BASIC_URL.to_owned() + x.icon.as_str();
                }
                file.seek(SeekFrom::Start(0)).await.unwrap();
                file.write_all(json!(vec).to_string().as_bytes())
                    .await
                    .unwrap();
                file.flush().await.unwrap();
            }
            Err(_) => {}
        }
    }
}
